package inutan.game.storage;

import bright.serialization.ByteBuf;
import inutan.data.Tables;
import org.ricks.common.event.ApplicationIEvent;
import org.ricks.common.event.ApplicationListener;
import org.ricks.common.lang.Assert;
import org.ricks.common.lang.Logger;
import org.ricks.common.utils.IoUtil;
import org.ricks.common.utils.TimeUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


/**
 * 数据上下文，策划数据装载策略。以便工程使用
 *
 * luban excel加载策划数据，最终方案
 */
public class StorageContext implements ApplicationListener<ApplicationIEvent> {

    /**
     * 临时数据，实例化Tables对象后 销毁tableDataMap
     */
    public static Map<String, byte[]> tableDataMap = new HashMap<>();
    private static Tables tables;

    /**
     * 策划数据装载进 用户上下文中
     * 容器启动，data热更，都需要调用 GameUserContext。loadTables(Tables) 策划数据装载进用户上下文中，以便业务使用
     * @param tables
     */
    public static void loadTables(Tables tables) {
        if(Objects.isNull(tables)) {
            Logger.error("[严重问题] 加载luban Tables异常，Tables初始化失败 或 data热更 !" );
            return;
        }
        StorageContext.tables = tables;
    }


    public static Tables tables() {
        Assert.notNull(tables,"警告容器没有装载进策划配置数据,");
        return StorageContext.tables;
    }


    /**
     * 策划数据加载
     *
     * @param event
     */
    @Override
    public void onApplicationEvent(ApplicationIEvent event) {
        if(event instanceof ApplicationStorageLoadEvent) {
            long startTime = TimeUtils.now();
            StorageContext.loadTables(loadTables());
            long endTime = TimeUtils.now();
            Logger.info("Storage started successfully and cost [" + (endTime - startTime) + "] millis");
        }
    }


    private Tables loadTables() {
        ObjectInputStream input = null;
        Object obj;
        try {
            File directory = new File("");
            String systemPath = directory.getAbsolutePath(); //load data.dat 路径 todo
            input = new ObjectInputStream(new FileInputStream(systemPath + "/data.dat"));
            obj = input.readObject();
            if (obj instanceof Map map) {
                tableDataMap = map;
                return new Tables(StorageContext::createByteBufFromFile);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IoUtil.close(input);
        }
        return null;
    }

    private static ByteBuf createByteBufFromFile(String file){
        ByteBuf buf = new ByteBuf(tableDataMap.get(file));
        return buf;
    }
}

